package main

import (
	"bytes"
	"encoding/binary"
	"log"
	"net"
	"time"
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8888")
	if err != nil {
		log.Fatal(err)
	}

	defer conn.Close()

	for {
		sendMessage(conn)
		time.Sleep(5 * time.Second)
	}
}

func sendMessage(conn net.Conn) {
	msg := "hello world"
	buf, err := packMessage(msg)
	if err != nil {
		log.Fatal(err)
	}

	_, err = conn.Write(buf)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("send data [%d], %v\n", len(msg), msg)
}

// packMessage 打包消息。
func packMessage(message string) ([]byte, error) {
	var err error
	buffer := bytes.NewBuffer(nil)
	// 直接用 uint64 保存 message 长度，会占用 8 字节（https://go.dev/ref/spec#Size_and_alignment_guarantees）
	// 好处是可以不用判断 message 的长度，因为不同的 message 长度（整型）在转化为字节数组时占用的长度不相同
	// 会导致在取 message 长度信息时需要做额外判断
	err = binary.Write(buffer, binary.BigEndian, uint64(len(message)))
	if err != nil {
		return nil, err
	}
	err = binary.Write(buffer, binary.BigEndian, []byte(message))
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}
